package com.xujie.sportsmeeting.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xujie.sportsmeeting.common.result.Result;
import com.xujie.sportsmeeting.dto.RoleDTO;
import com.xujie.sportsmeeting.dto.RoleQueryDTO;
import com.xujie.sportsmeeting.entity.SysRole;
import com.xujie.sportsmeeting.entity.SysPermission;
import com.xujie.sportsmeeting.service.SysRoleService;
import com.xujie.sportsmeeting.vo.RoleVO;
import com.xujie.sportsmeeting.vo.PermissionVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色管理控制器
 */
@Tag(name = "角色管理", description = "角色管理相关接口")
@RestController
@RequestMapping("/role")
@RequiredArgsConstructor
public class RoleController {

    private final SysRoleService sysRoleService;

    @Operation(summary = "获取角色列表")
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('system:role') or authentication.name == 'admin'")
    public Result<IPage<RoleVO>> getRoleList(RoleQueryDTO queryDTO) {
        IPage<SysRole> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        IPage<SysRole> rolePage = sysRoleService.getRolePage(page, queryDTO);
        
        // 转换为VO
        IPage<RoleVO> voPage = rolePage.convert(role -> {
            RoleVO vo = new RoleVO();
            BeanUtils.copyProperties(role, vo);
            // 获取角色权限
            vo.setPermissions(sysRoleService.findPermissionsByRoleId(role.getId()));
            return vo;
        });
        
        return Result.success(voPage);
    }

    @Operation(summary = "获取角色详情")
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('system:role') or authentication.name == 'admin'")
    public Result<RoleVO> getRoleDetail(@PathVariable Long id) {
        SysRole role = sysRoleService.getById(id);
        if (role == null) {
            return Result.error("角色不存在");
        }
        
        RoleVO vo = new RoleVO();
        BeanUtils.copyProperties(role, vo);
        vo.setPermissions(sysRoleService.findPermissionsByRoleId(id));
        vo.setPermissionIds(sysRoleService.findPermissionIdsByRoleId(id));
        
        return Result.success(vo);
    }

    @Operation(summary = "创建角色")
    @PostMapping
    @PreAuthorize("hasAuthority('system:role:add') or authentication.name == 'admin'")
    public Result<Void> createRole(@Valid @RequestBody RoleDTO roleDTO) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(roleDTO, role);
        
        boolean success = sysRoleService.createRole(role);
        if (success) {
            return Result.success("角色创建成功");
        } else {
            return Result.error("角色创建失败");
        }
    }

    @Operation(summary = "更新角色信息")
    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('system:role:edit') or authentication.name == 'admin'")
    public Result<Void> updateRole(@PathVariable Long id, @Valid @RequestBody RoleDTO roleDTO) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(roleDTO, role);
        role.setId(id);
        
        boolean success = sysRoleService.updateRole(role);
        if (success) {
            return Result.success("角色更新成功");
        } else {
            return Result.error("角色更新失败");
        }
    }

    @Operation(summary = "删除角色")
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('system:role:delete') or authentication.name == 'admin'")
    public Result<Void> deleteRole(@PathVariable Long id) {
        boolean success = sysRoleService.removeById(id);
        if (success) {
            return Result.success("角色删除成功");
        } else {
            return Result.error("角色删除失败");
        }
    }

    @Operation(summary = "批量删除角色")
    @DeleteMapping("/batch")
    @PreAuthorize("hasAuthority('system:role:delete') or authentication.name == 'admin'")
    public Result<Void> batchDeleteRoles(@RequestBody List<Long> ids) {
        boolean success = sysRoleService.removeByIds(ids);
        if (success) {
            return Result.success("批量删除成功");
        } else {
            return Result.error("批量删除失败");
        }
    }

    @Operation(summary = "启用/禁用角色")
    @PutMapping("/{id}/status")
    @PreAuthorize("hasAuthority('system:role:edit') or authentication.name == 'admin'")
    public Result<Void> toggleRoleStatus(@PathVariable Long id, @RequestBody StatusRequest request) {
        boolean success = sysRoleService.updateRoleStatus(id, request.getStatus());
        if (success) {
            return Result.success("角色状态更新成功");
        } else {
            return Result.error("角色状态更新失败");
        }
    }

    @Operation(summary = "获取权限列表")
    @GetMapping("/permissions")
    @PreAuthorize("hasAuthority('system:role') or authentication.name == 'admin'")
    public Result<List<PermissionVO>> getPermissionList() {
        List<PermissionVO> permissions = sysRoleService.getAllPermissions();
        return Result.success(permissions);
    }

    @Operation(summary = "分配角色权限")
    @PutMapping("/{roleId}/permissions")
    @PreAuthorize("hasAuthority('system:role:edit') or authentication.name == 'admin'")
    public Result<Void> assignRolePermissions(@PathVariable Long roleId, @RequestBody AssignPermissionsRequest request) {
        boolean success = sysRoleService.assignRolePermissions(roleId, request.getPermissionIds());
        if (success) {
            return Result.success("权限分配成功");
        } else {
            return Result.error("权限分配失败");
        }
    }

    // 内部请求类
    public static class StatusRequest {
        private Integer status;
        
        public Integer getStatus() {
            return status;
        }
        
        public void setStatus(Integer status) {
            this.status = status;
        }
    }

    public static class AssignPermissionsRequest {
        private List<Long> permissionIds;
        
        public List<Long> getPermissionIds() {
            return permissionIds;
        }
        
        public void setPermissionIds(List<Long> permissionIds) {
            this.permissionIds = permissionIds;
        }
    }
}
